package com.note.service.impl;

import com.note.common.core.domain.model.LoginUser;
import com.note.common.utils.StringUtils;
import com.note.config.SftpProperties;
import com.note.domain.NoteInfo;
import com.note.domain.SftpContext;
import com.note.mapper.NoteInfoMapper;
import com.note.mq.configure.RabbitMqProperties;
import com.note.mq.entity.MsgData;
import com.note.mq.service.MqSendMsgI;
import com.note.request.NoteSaveRequest;
import com.note.service.FilePathProductServiceI;
import com.note.service.FileSystemService;
import com.note.service.INoteInfoService;
import com.note.service.ISysUserNotedService;
import com.note.util.Text2HtmUtil;
import com.rabbitmq.client.Channel;
import org.apache.tika.Tika;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;


/**
 * 【请填写功能名称】Service业务层处理
 * 
 * @author ruoyi
 * @date 2021-01-07
 */
@Service
@Transactional
public class NoteInfoServiceImpl implements INoteInfoService
{
    @Autowired
    private NoteInfoMapper noteInfoMapper;
    @Autowired
    private ISysUserNotedService iSysUserNotedService;
    @Autowired
    private FileSystemService fileSystemService;
    @Autowired
    FilePathProductServiceI filePathProductService;
    @Autowired
    SftpProperties sftpProperties;
    @Autowired
    MqSendMsgI mqSendMsgI;


    @Autowired
    RabbitMqProperties rabbitMqProperties;

    /**
     * 查询【请填写功能名称】
     * 
     * @param id 【请填写功能名称】ID
     * @return 【请填写功能名称】
     */
    @Override
    public NoteInfo selectNoteInfoById(Long id)
    {
        return noteInfoMapper.selectNoteInfoById(id);
    }

    /**
     * 查询【请填写功能名称】列表
     * 
     * @param noteInfo 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<NoteInfo> selectNoteInfoList(NoteInfo noteInfo)
    {
        return noteInfoMapper.selectNoteInfoList(noteInfo);
    }

    /**
     * 新增【请填写功能名称】
     * 
     * @param noteInfo 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int insertNoteInfo(NoteInfo noteInfo)
    {
        return noteInfoMapper.insertNoteInfo(noteInfo);
    }

    /**
     * 修改【请填写功能名称】
     * 
     * @param noteInfo 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int updateNoteInfo(NoteInfo noteInfo)
    {
        return noteInfoMapper.updateNoteInfo(noteInfo);
    }

    /**
     * 批量删除【请填写功能名称】
     * 
     * @param ids 需要删除的【请填写功能名称】ID
     * @return 结果
     */
    @Override
    public int deleteNoteInfoByIds(String[] ids)
    {
        return noteInfoMapper.deleteNoteInfoByIds(ids);
    }

    /**
     * 删除【请填写功能名称】信息
     * 
     * @param id 【请填写功能名称】ID
     * @return 结果
     */
    @Override
    public int deleteNoteInfoById(String id)
    {
        return noteInfoMapper.deleteNoteInfoById(id);
    }


    @Override
    public void saveNote(NoteSaveRequest noteSaveRequest,  LoginUser loginUser, MultipartFile[] files) throws Exception {
        SftpContext sftpContext = new SftpContext();
        sftpContext.setUserName(loginUser.getUsername());
        List<NoteInfo> noteInfoList = new ArrayList<>();
        if(StringUtils.isNotBlank(noteSaveRequest.getText())){
            NoteInfo noteInfo = new NoteInfo();
            //非空代表是富文本上传笔记
            //先插入db，后生成HTML文档，再上传到sftp
            sftpContext.setSubbfix("html");
            InputStream inputStream = Text2HtmUtil.formToHtml(noteSaveRequest.getText());
            String path = filePathProductService.productSftpPath(sftpContext);
            boolean upLoadSuccess = fileSystemService.uploadFile(path, inputStream);
            if(!upLoadSuccess){
                throw new RuntimeException("文件上传不成功");
            }
            noteInfo.setCreateDate(new Date());
            noteInfo.setFileSuffix("html");
            noteInfo.setFileUrl(path);
            noteInfo.setNoteName(noteSaveRequest.getTitle());
            noteInfo.setCreateUser(loginUser.getUser().getUserId());
            noteInfo.setFileText(noteSaveRequest.getText());
            noteInfo.setTags(noteSaveRequest.getTags());
            noteInfoList.add(noteInfo);
            //保存用户与笔记的关系 。不用保存，sys_user_noted 只当用户收藏这笔记时，才往此表插入记录

        }else {
            //上传文件形式
            Tika tika = new Tika();
            for(MultipartFile multipartFile : files){
                int idx = multipartFile.getOriginalFilename().lastIndexOf(".");
                String subbfix = multipartFile.getOriginalFilename().substring(idx+1);
                sftpContext.setSubbfix(subbfix);
                String path = filePathProductService.productSftpPath(sftpContext);
                boolean upLoadSuccess = fileSystemService.uploadFile(path, multipartFile.getInputStream());
                if(!upLoadSuccess){
                    throw new RuntimeException("文件上传不成功");
                }
                String fileText = tika.parseToString(multipartFile.getInputStream());
                NoteInfo noteInfo = new NoteInfo();
                noteInfo.setCreateDate(new Date());
                noteInfo.setFileSuffix(subbfix);
                noteInfo.setFileUrl(path);
                noteInfo.setNoteName(multipartFile.getOriginalFilename());
                noteInfo.setCreateUser(loginUser.getUser().getUserId());
                noteInfo.setFileText(fileText);
                noteInfoList.add(noteInfo);
            }

        }
        noteInfoMapper.batchSave(noteInfoList);
        Map<String, Object> sendMsgMap = new HashMap<>();

        //这里一般一次上传只有一个文件
        noteInfoList.forEach(x -> {
            sendMsgMap.put("noteId", x.getId());
            sendMsgMap.put("url", x.getFileUrl());
        });

        MsgData msgData = MsgData.buildMsg(rabbitMqProperties.getQueuename(), rabbitMqProperties.getExchangename(), sendMsgMap);
        mqSendMsgI.sendMsg(msgData);
    }



    @Override
    public NoteInfo detail(Long noteId) {
        NoteInfo sysUserNoted = noteInfoMapper.selectNoteInfoById(noteId);
        return sysUserNoted;
    }

    @Override
    public void update(NoteInfo noteInfo) {
        noteInfoMapper.update(noteInfo);
    }


    @Override
    public File exportToHtml(Long noteId) throws Exception {
        NoteInfo noteInfo = noteInfoMapper.selectNoteInfoById(noteId);
        File file = fileSystemService.downloadFile(noteInfo.getFileUrl());
        return file;
    }


    @RabbitListener(queues = "${rabbitmq.fileurlqueuename}")
    public void receive(Map<String, Object> msg, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
        try {
            Long noteId = (Long) msg.get("noteId");
            //获取到预览的url
            String previewUrl = (String) msg.get("url");
            NoteInfo noteInfo = new NoteInfo();
            noteInfo.setId(noteId);
            noteInfo.setPreviewUrl(previewUrl);
            noteInfoMapper.updateNoteInfo(noteInfo);
            channel.basicAck(tag, false);
        } catch (IOException e) {
            e.printStackTrace();
            channel.basicReject(tag, false);
        }

    }
}
